package com.bkgy.controller.technology.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bkgy.controller.technology.entity.TTechTcm2280Param;
import com.bkgy.controller.technology.entity.Tcm2280ProcessDatas;
import com.bkgy.controller.technology.mapper.ITechTcmParamMapper;
import com.bkgy.controller.technology.service.ITechTcmParamService;
import com.bkgy.modular.datacollect_bx.bean.JDataSavemong2280_1;
import com.bkgy.sys.common.entity.ResultData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class TechTcmParamServiceImpl extends ServiceImpl<ITechTcmParamMapper, TTechTcm2280Param> implements ITechTcmParamService {
    private final MongoTemplate mongoTemplate;

    @Override
    public void checkParam(Map<String, TTechTcm2280Param> paramMap, Tcm2280ProcessDatas obj) {
        //格式化不规则数据
        String surface = obj.getSurfaceAccuClassCode();
        //表面代码是空或者31都按30计
        if (StringUtils.isBlank(obj.getSurfaceAccuClassCode()) || "31".equals(obj.getSurfaceAccuClassCode())) {
            surface = "30";
        } else if ("50".equals(obj.getSurfaceAccuClassCode()) || "51".equals(obj.getSurfaceAccuClassCode())) {
            surface = "50/51";
        }
        String zhibiao = "";
        if (StringUtils.isNotEmpty(obj.getSaleOrderNo()) && obj.getSaleOrderNo().startsWith("G")) {
            zhibiao = "镀锌";
        }
        String steelClass = "";
        if (StringUtils.isNotEmpty(obj.getSteelclass())) {
            steelClass = obj.getSteelclass();
        }
        String comp = "";
        if (StringUtils.isNotEmpty(obj.getFinCustCname())) {
            if (obj.getFinCustCname().startsWith("上汽")) {
                comp = "上汽";
            } else if (obj.getFinCustCname().indexOf("日产") != -1) {
                comp = "日产";
            }
        }

        String keySuff = surface + "_" + zhibiao + "_" + steelClass + "_" + comp;
        //工艺段速度
        obj.setTcmProcessSpeedJudge(checkRange(obj.getTcmProcessSpeedAvg(), paramMap, 1 + keySuff, obj.getExtid(), null));
        //1#酸槽温度
        obj.setTcmTank1TempJudge(checkRange(obj.getTcmTank1TempAvg(), paramMap, 2 + keySuff, obj.getExtid(), null));
        //2#酸槽温度
        obj.setTcmTank2TempJudge(checkRange(obj.getTcmTank2TempAvg(), paramMap, 2 + keySuff, obj.getExtid(), null));
        // 3#酸槽温度
        obj.setTcmTank3TempJudge(checkRange(obj.getTcmTank3TempAvg(), paramMap, 2 + keySuff, obj.getExtid(), null));
        //漂洗槽PH值
        obj.setTcmRinsePhJudge(checkRange(obj.getTcmRinsePhAvg(), paramMap, 4 + keySuff, obj.getExtid(), null));
        //烘干机温度
        obj.setTcmDryTempJudge(checkRange(BigDecimal.ZERO, paramMap, 5 + keySuff, obj.getExtid(), "tcm_dry_temp"));
        //轧制速度，只有日产、上汽有规则，其他不限制，都认为正常
        int i = checkRange(obj.getRollSpeedAvg(), paramMap, 6 + keySuff, obj.getExtid(), null);
        obj.setRollSpeedJudge(i == -2 ? 0 : i);
        //乳化液1#箱温度
        obj.setTcmTank1EmuTempJudge(checkRange(BigDecimal.ZERO, paramMap, 8 + keySuff, obj.getExtid(), "tcm_tank1_emu_temp"));
        //乳化液2#箱温度
        obj.setTcmTank2EmuTempJudge(checkRange(BigDecimal.ZERO, paramMap, 8 + keySuff, obj.getExtid(), "tcm_tank2_emu_temp"));
        //乳化液3#箱温度
        obj.setTcmTank3EmuTempJudge(checkRange(BigDecimal.ZERO, paramMap, 8 + keySuff, obj.getExtid(), "tcm_tank3_emu_temp"));
        //1#乳化液喷射梁压力
        obj.setTcm1RuPressureJudge(checkRange(obj.getTcm1RuPressureAvg(), paramMap, 10 + keySuff, obj.getExtid(), null));
        //2#乳化液喷射梁压力
        obj.setTcm2RuPressureJudge(checkRange(obj.getTcm2RuPressureAvg(), paramMap, 10 + keySuff, obj.getExtid(), null));
        //3#乳化液喷射梁压力
        obj.setTcm3RuPressureJudge(checkRange(obj.getTcm3RuPressureAvg(), paramMap, 10 + keySuff, obj.getExtid(), null));
        //4#乳化液喷射梁压力
        obj.setTcm4RuPressureJudge(checkRange(obj.getTcm4RuPressureAvg(), paramMap, 10 + keySuff, obj.getExtid(), null));
        //5#乳化液喷射梁压力
        obj.setTcm5RuPressureJudge(checkRange(obj.getTcm5RuPressureAvg(), paramMap, 10 + keySuff, obj.getExtid(), null));
        //拉矫机延伸率
        obj.setTcmTlElongJudge(checkRange(BigDecimal.ZERO, paramMap, 13 + keySuff, obj.getExtid(), "tcm_tl_elong"));
        //1#游离酸浓度
        obj.setAcidJudge1(checkRange(obj.getAcid1(), paramMap, 14 + keySuff, obj.getExtid(), null));
        //3#游离酸浓度
        obj.setAcidJudge3(checkRange(obj.getAcid3(), paramMap, 15 + keySuff, obj.getExtid(), null));
        //1#铁离子浓度
        obj.setFeContentJudge1(checkRange(obj.getFeContent1(), paramMap, 16 + keySuff, obj.getExtid(), null));
        //3#铁离子浓度
        obj.setFeContentJudge3(checkRange(obj.getFeContent3(), paramMap, 17 + keySuff, obj.getExtid(), null));
    }

    public int checkRange(BigDecimal checkValue, Map<String, TTechTcm2280Param> paramMap, String key, String extId, String paramName) {
        if (checkValue == null) {
            return -1;
        }
        if (!paramMap.containsKey(key)) {
            //降级验证，去掉钢种指标（IF钢、CQ级别这些）
            String[] arr = key.split("_", -1);
            key = arr[0] + "_" + arr[1] + "__" + arr[3];
            if (!paramMap.containsKey(key)) {
                key = arr[0] + "___";
                if (!paramMap.containsKey(key)) {
                    log.warn("卷号 {} 缺少验证标准，key：{}", extId, key);
                    return -2;
                }
            }
        }

        //12项指标(第一位占位),tcm_dry_temp烘干机温度
        //按曲线方式验证
        boolean checkCurveFlag = false;
        List<Double> curveList = new ArrayList<>();
        //用开头数字识别验证的是什么指标
        int start = Integer.parseInt(key.substring(0, 1));
        if (paramName != null) {
            curveList = loadCurve(extId, paramName);
            checkCurveFlag = true;
        }

        TTechTcm2280Param techParam = paramMap.get(key);
        String panding = techParam.getPanding();
        if (panding.startsWith("t")) {
            //单向范围
            String c = panding.substring(1, 2);
            BigDecimal levelValue = BigDecimal.valueOf(Double.parseDouble(panding.substring(2)));
            if (checkCurveFlag) {
                return checkCurve(curveList, c, levelValue.doubleValue());
            } else {
                if ("≥".equals(c)) {
                    if (checkValue.compareTo(levelValue) >= 0) return 0;
                    else return 1;
                } else if ("≤".equals(c)) {
                    if (checkValue.compareTo(levelValue) <= 0) return 0;
                    else return 1;
                } else if ("＞".equals(c)) {
                    if (checkValue.compareTo(levelValue) > 0) return 0;
                    else return 1;
                } else if ("＜".equals(c)) {
                    if (checkValue.compareTo(levelValue) < 0) return 0;
                    else return 1;
                }
            }
        } else {
            //区间范围
            BigDecimal w1 = BigDecimal.valueOf(Double.parseDouble(panding.substring(0, panding.indexOf("t") - 1)));
            BigDecimal w2 = BigDecimal.valueOf(Double.parseDouble(panding.substring(panding.indexOf("t") + 2)));
            if (checkCurveFlag) {
                return checkCurve(curveList, w1.doubleValue(), w2.doubleValue(), extId);
            } else {
                if (checkValue.compareTo(w1) >= 0 && checkValue.compareTo(w2) <= 0) return 0;
                else return 1;
            }
        }
        log.warn("酸轧工艺符合度分析，卷号{},未命中规则", extId);
        return -3;
    }

    /**
     * 单边界验证，有连续20个值超范围，验证为不合格
     *
     * @param curveList  数值列表
     * @param c          操作符
     * @param levelValue
     * @return 0正常，1不正常
     */
    private int checkCurve(List<Double> curveList, String c, Double levelValue) {
        int rank = 20;//连续20个超限为不合格
        if (curveList == null || curveList.size() < rank) return -3;
        int flag = 0;
        if ("≥".equals(c)) {
            //从某一个点开始向后的20个数据
            for (int i = 0; i <= curveList.size() - rank; i++) {
                boolean allExceed = true;
                for (int j = i; j < i + rank; j++) {
                    if (curveList.get(j) >= levelValue) {
                        allExceed = false;
                        break;
                    }
                }
                if (allExceed) {//遍历完毕，没有在范围内的
                    flag = 1;
                    break;
                }
            }
            return flag;
        } else if ("≤".equals(c)) {
            for (int i = 0; i <= curveList.size() - rank; i++) {
                boolean allExceed = true;
                for (int j = i; j < i + rank; j++) {
                    if (curveList.get(j) <= levelValue) {
                        allExceed = false;
                        break;
                    }
                }
                if (allExceed) {//遍历完毕，没有在范围内的
                    flag = 1;
                    break;
                }
            }
            return flag;
        } else if ("＞".equals(c)) {
            for (int i = 0; i <= curveList.size() - rank; i++) {
                boolean allExceed = true;
                for (int j = i; j < i + rank; j++) {
                    if (curveList.get(j) > levelValue) {
                        allExceed = false;
                        break;
                    }
                }
                if (allExceed) {//遍历完毕，没有在范围内的
                    flag = 1;
                    break;
                }
            }
            return flag;
        } else if ("＜".equals(c)) {
            for (int i = 0; i <= curveList.size() - rank; i++) {
                boolean allExceed = true;
                for (int j = i; j < i + rank; j++) {
                    if (curveList.get(j) < levelValue) {
                        allExceed = false;
                        break;
                    }
                }
                if (allExceed) {//遍历完毕，没有连续超范围的
                    flag = 1;
                    break;
                }
            }
            return flag;
        }
        return -3;
    }

    /**
     * 双边界验证，有连续20个值超范围，验证为不合格
     */
    private int checkCurve(List<Double> curveList, double startLevel, double endLevel, String extId) {
        int rank = 20;//连续20个不在范围，判定不合格
        if (curveList == null || curveList.size() < rank) {
            log.warn("卷号 {} 的酸轧曲线未获取到", extId);
            return -3;
        }

        int flag = 0;
        for (int i = 0; i <= curveList.size() - rank; i++) {
            boolean allExceed = true;
            for (int j = i; j < i + rank; j++) {
                if (curveList.get(j) >= startLevel && curveList.get(j) <= endLevel) {
                    allExceed = false;
                    break;
                }
            }
            if (allExceed) {//遍历完毕，没有连续超范围的
                flag = 1;
                break;
            }
        }
        return flag;
    }

    private List<Double> loadCurve(String extId, String var_name) {
        Query query = new Query(Criteria.where("extid").is(extId).and("var_name").is(var_name));
        JDataSavemong2280_1 obj = mongoTemplate.findOne(query, JDataSavemong2280_1.class);
        List<Double> sList = new ArrayList<>();
        if (obj != null) {
            for (Double data : obj.getCurve()) {
                sList.add(data);
            }
        }
        return sList;
    }

    @Override
    public ResultData<String> importTechParam() {
        FileInputStream in = null;
        try {
            in = new FileInputStream("D:\\workspace\\项目文档\\生产工艺分析\\酸轧生产工艺分析\\工艺参数转存入库.xlsx");
            XSSFWorkbook excel = new XSSFWorkbook(in);
            XSSFSheet sheet = excel.getSheetAt(0);
            int lastRowNum = sheet.getLastRowNum();

            for (int i = 1; i <= lastRowNum; i++) {
                XSSFRow row = sheet.getRow(i);
                double col0 = row.getCell(0).getNumericCellValue();
                String col1 = row.getCell(1).getStringCellValue();
                String col2 = row.getCell(2).getStringCellValue();
                String col3 = row.getCell(3).getStringCellValue();
                String col4 = row.getCell(4).getStringCellValue();
                String col5 = row.getCell(5).getStringCellValue();
                String col6 = row.getCell(6).getStringCellValue();

                TTechTcm2280Param param = new TTechTcm2280Param();
                param.setProNo(col0 + "");
                param.setProName(col1);
                param.setSurface(col2);
                param.setZhibiao(col3);
                param.setBrand(col4);
                param.setCompany(col5);
                param.setPanding(col6);
                save(param);
            }
            excel.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return ResultData.ResultDataSuccess("success");
    }
}
